#ifndef xpack_test_lang_cxx_strlize
#define xpack_test_lang_cxx_strlize
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::test_lang_cxx_strlize::inc
#include"chrono/datetime.hpp"
#include"chrono/date.hpp"
#include"chrono/time.hpp"
#include"test/helper.hpp" // 需要放第一
#include"lang/cxx/strlize.hpp"
#include"lang/cxx/parse.hpp"
#include"lang/cxx.hpp"
#include"math/random.hpp"
#include"memop/copy.hpp"
#include"utils/array.hpp"
#include<stdio.h>
#include<math.h>
#pragma pop_macro("xuser")

namespace mixc::test_lang_cxx_strlize{
    xtest("strlize"){
        char buffer_a[128];
        char buffer_b[128];
        char * ptr_b = buffer_b;
        auto str_b = inc::c08(ptr_b/*消除编译警告*/, 0); 
        auto alloc = [&](uxx){
            return buffer_a;
        };

        auto stream = [&](const char * content, uxx length){
            inc::copy(ptr_b, content, length);
            ptr_b += length;
            str_b->length = ptr_b - buffer_b;
        };


        for(uxx i = 0; i < 100000; i++){
            auto value64 = inc::random<f64>();
            auto value32 = inc::random<f32>();
            inc::c08(value64, alloc);

            xassert_fe(f64(inc::c08(value64, alloc).parse<f64>()), value64){
                inc::c08(value64, alloc);
                printf("%f\n", value64);
            }

            xassert_epsilson_scoped(1e-5);
            xassert_fe(f64(inc::c08(value32, alloc).parse<f64>()), f64(value32)){
                printf("%f\n", value32);
            }
        }

        ptr_b       = buffer_b;
        xassert_eq(inc::c08(1.25f, stream)->length, 0u);
        xassert_eq("1.25", str_b);

        #undef  xgen_float
        #define xgen_float(VALUE)                                                                                               \
        {                                                                                                                       \
            xassert_fe(f64(inc::c08(VALUE, alloc).parse<f64>()), VALUE){ printf("%f\n", VALUE); }                               \
            xassert_epsilson_scoped(1e-5);                                                                                      \
            xassert_fe(f64(inc::c08(f32(VALUE), alloc).parse<f64>()), f64(VALUE)){ printf("%f\n", VALUE); }                     \
        }

        if (false) for(f64 i = -100000.0; i < 100000.0; i += 1){
            f64 v00 = i / 1000.0;
            f64 v01 = v00 + 0.5;
            f64 v02 = v00 - 0.5;
            f64 v03 = v00 + 0.05;
            f64 v04 = v00 - 0.05;
            f64 v05 = v00 + 0.005;
            f64 v06 = v00 - 0.005;
            f64 v07 = v00 + 0.0005;
            f64 v08 = v00 - 0.0005;
            f64 v09 = v00 + 0.00005;
            f64 v10 = v00 - 0.00005;
            f64 v11 = v00 + 0.000005;
            f64 v12 = v00 - 0.000005;
            f64 v13 = v00 + 0.0000005;
            f64 v14 = v00 - 0.0000005;
            f64 v15 = v00 + 0.00000005;
            f64 v16 = v00 - 0.00000005;

            xgen_float(v00);
            xgen_float(v01);
            xgen_float(v02);
            xgen_float(v03);
            xgen_float(v04);
            xgen_float(v05);
            xgen_float(v06);
            xgen_float(v07);
            xgen_float(v08);
            xgen_float(v09);
            xgen_float(v10);
            xgen_float(v11);
            xgen_float(v12);
            xgen_float(v13);
            xgen_float(v14);
            xgen_float(v15);
            xgen_float(v16);
        }

        xgen_float(+12.0);
        xgen_float(-12.0);
        xgen_float(+1.5);
        xgen_float(+1.25);
        xgen_float(+1.125);
        xgen_float(+1.0);
        xgen_float(+0.0);

        xgen_float(+1.5);
        xgen_float(-1.5);

        xgen_float(+0.5);
        xgen_float(-0.5);

        xgen_float(+0.25);
        xgen_float(-0.25);

        xgen_float(+0.25);
        xgen_float(-0.25);

        xgen_float(+0.125);
        xgen_float(-0.125);

        #undef  xgen_float
        #define xgen_float(P,VALUE)                                                                                             \
            {                                                                                                                   \
                f64 expect = round(VALUE);                                                                                      \
                xassert_fe(f64(inc::c08(VALUE, inc::float_format_t::fmt_sn, P, alloc).parse<f64>()), expect){ xhint(i); }       \
            }

        for(uxx i = 0; i < 1000; i++){
            xgen_float(0, +1.50 + i);
            xgen_float(0, +1.40 + i);
            xgen_float(0, -1.50 + i);
            xgen_float(0, -1.40 + i);
            xgen_float(0, -1.06 + i);
            xgen_float(0, -1.04 + i);
            xgen_float(0, -1.00 + i);
        }

        #undef  xgen_float
        #define xgen_float(P,VALUE)                                                                                             \
            {                                                                                                                   \
                char fmt[16];                                                                                                   \
                f64 expect = 0;                                                                                                 \
                snprintf(fmt, sizeof(fmt), "%%.%df", P);                                                                        \
                snprintf(buffer_a, sizeof(buffer_a), fmt, VALUE);                                                               \
                sscanf(buffer_a, "%lf", &expect);                                                                               \
                xassert_fe(f64(inc::c08(VALUE, inc::float_format_t::fmt_sn, P, alloc).parse<f64>()), expect){ xhint(i); } \
            }

        for(uxx i = 0; i < 1000; i++){
            xgen_float(1, +1.060 + i);
            xgen_float(1, +1.040 + i);
            xgen_float(1, -1.060 + i);
            xgen_float(1, -1.040 + i);
            xgen_float(1, -1.006 + i);
            xgen_float(1, -1.004 + i);
            xgen_float(1, -1.000 + i);
        }

        for(uxx i = 0; i < 1000; i++){
            xgen_float(2, +1.0060 + i);
            xgen_float(2, +1.0040 + i);
            xgen_float(2, -1.0060 + i);
            xgen_float(2, -1.0040 + i);
            xgen_float(2, -1.0006 + i);
            xgen_float(2, -1.0004 + i);
            xgen_float(2, -1.0000 + i);
        }

        for(uxx i = 0; i < 1000; i++){
            xgen_float(3, +1.10060 + i);
            xgen_float(3, +1.10040 + i);
            xgen_float(3, -1.10060 + i);
            xgen_float(3, -1.10040 + i);
            xgen_float(3, -1.10006 + i);
            xgen_float(3, -1.10004 + i);
            xgen_float(3, -1.10000 + i);
        }

        for(uxx i = 0; i < 1000; i++){
            xgen_float(4, +1.010060 + i);
            xgen_float(4, +1.010040 + i);
            xgen_float(4, -1.010060 + i);
            xgen_float(4, -1.010040 + i);
            xgen_float(4, -1.010006 + i);
            xgen_float(4, -1.010004 + i);
            xgen_float(4, -1.010000 + i);
        }

        for(uxx i = 0; i < 1000; i++){
            xgen_float(2, +1.0010060 + i);
            xgen_float(2, +1.0010040 + i);
            xgen_float(2, -1.0010060 + i);
            xgen_float(2, -1.0010040 + i);
            xgen_float(2, -1.0010006 + i);
            xgen_float(2, -1.0010004 + i);
            xgen_float(2, -1.0010000 + i);
        }

        #undef  xgen_float

        #define xgen_datetime(STR_DATE,STR_TIME,...)                \
        {                                                           \
            auto datetime       = inc::datetime(__VA_ARGS__);       \
            auto str_datetime   = inc::c08(datetime, alloc);        \
            char token[]        = STR_DATE " " STR_TIME;            \
            xassert_eq(str_datetime, token);                        \
                                                                    \
            auto date           = inc::date(datetime);              \
            auto str_date       = inc::c08(date, alloc);            \
            xassert_eq(str_date, STR_DATE);                         \
                                                                    \
            auto time           = inc::time(datetime);            \
            auto str_time       = inc::c08(time, alloc);            \
            xassert_eq(str_time, STR_TIME);                         \
        }

        xgen_datetime("00/01/01",  "01:01:01",   0, 1, 1,  1, 1, 1);
        xgen_datetime("10/01/01",  "01:01:01",  10, 1, 1,  1, 1, 1);
        xgen_datetime("100/01/01", "01:01:01", 100, 1, 1,  1, 1, 1);

        xgen_datetime("2024/01/01", "01:01:01", 2024, 1, 1,  1, 1, 1);
        xgen_datetime("2024/01/01", "01:01:10", 2024, 1, 1,  1, 1,10);
        xgen_datetime("2024/01/01", "01:10:10", 2024, 1, 1,  1,10,10);
        xgen_datetime("2024/01/01", "10:10:10", 2024, 1, 1, 10,10,10);
        xgen_datetime("2024/01/10", "10:10:10", 2024, 1,10, 10,10,10);
        xgen_datetime("2024/10/10", "10:10:10", 2024,10,10, 10,10,10);

        #undef  xgen_datetime
    };
}

#endif